package com.nsn.das.midas.service.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.nsn.das.midas.service.BaseManager;

@Service("baseManager")
public class BaseManagerImpl implements BaseManager{
	protected final Log log = LogFactory.getLog(getClass());

    @Resource
    private SessionFactory sessionFactory;
    private HibernateTemplate hibernateTemplate;

    protected SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    protected Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    protected HibernateTemplate getHibernateTemplate() {
        if (hibernateTemplate == null) {
            hibernateTemplate = new HibernateTemplate(sessionFactory);
        }
        return hibernateTemplate;
    }

    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }
    
    @Override
    public <T> T getEntity(Class<T> clazz,long id){
    	return this.getHibernateTemplate().get(clazz, id);
    }
    
    @Override
    public void saveEntity(Object entity){
    	this.getHibernateTemplate().save(entity);
    }
    
    @Override
    public void saveOrUpdateEntity(Object entity){
    	this.getHibernateTemplate().saveOrUpdate(entity);
    }
    
    @Override
    public void deleteEntity(Object entity){
    	this.getHibernateTemplate().delete(entity);
    }
    
    @Override
    public <T> Set<T> getEntitysByIds(Class<T> clazz,String ids){
    	Set<T> entitys = new HashSet<T>();
    	if(StringUtils.hasText(ids)){
    		for(String id : ids.trim().split(",")){
    			entitys.add(this.getEntity(clazz, Long.parseLong(id.trim())));
    		}
    	}
		
		return entitys;
	}
    
    @SuppressWarnings("unchecked")
	@Override
    public <T> List<T> getEntities(Class<T> clazz, int pageIndex, int pageSize){
    	return this.getSession().createCriteria(clazz)
    			.setFirstResult((pageIndex - 1) * pageSize)
    			.setMaxResults(pageSize)
    			.list();
    }
    
    @Override
    public <T> long countEntities(Class<T> clazz){
    	return (Long)this.getSession().createCriteria(clazz).setProjection(Projections.rowCount()).uniqueResult();
    }

	@SuppressWarnings("unchecked")
	@Override
	public <T> List<T> getEntities(Map<String, Object> conditions, Class<T> clazz, int pageIndex, int pageSize) {
		Criteria targetC;
		String propertyName;
		Criteria c = this.getSession().createCriteria(clazz);
		targetC = c;
		if(conditions != null){
			for(String property : conditions.keySet()){
				String[] oriPropertyName = property.split(",");
				String opt = oriPropertyName.length == 2 ? oriPropertyName[1] : "LIKE";
				propertyName = oriPropertyName[0];
				if(oriPropertyName[0].split("\\.").length == 2){
					Criteria subC = c.createCriteria(oriPropertyName[0].split("\\.")[0]);
					targetC = subC;
					propertyName = oriPropertyName[0].split("\\.")[1];
				}
				if(opt.equals("LIKE")){
					targetC.add(Restrictions.like(propertyName, (String)conditions.get(property),MatchMode.ANYWHERE));
				}else{
					targetC.add(Restrictions.eq(propertyName, conditions.get(property)));
				}
			}
		}
		c.setFirstResult((pageIndex - 1) * pageSize);
		c.setMaxResults(pageSize);
		
		return c.list();
	}
}